// FEAT3: Finite Element Analysis Toolbox, Version 3
// Copyright (C) 2010 - 2020 by Stefan Turek & the FEAT group
// FEAT3 is released under the GNU General Public License version 3,
// see the file 'copyright.txt' in the top level directory for details.

#include <kernel/geometry/test_aux/validate_structured_meshes.hpp>
#include <kernel/geometry/test_aux/copy_comp_set.hpp>

namespace FEAT
{
  namespace Geometry
  {
    namespace TestAux
    {
      void validate_structured_mesh_2d(const StructuredMesh<2>* mesh)
      {

        // validate sizes
        if(mesh->get_num_entities(0) != 21)
          throw String("Vertex count mismatch");
        if(mesh->get_num_entities(1) != 32)
          throw String("Edge count mismatch");
        if(mesh->get_num_entities(2) != 12)
          throw String("Quad count mismatch");

        // vertices-at-edge array
        static const Index v_e[] =
        {
          0, 1,
          1, 2,
          2, 3,
          3, 4,
          4, 5,
          5, 6,
          7, 8,
          8, 9,
          9, 10,
          10, 11,
          11, 12,
          12, 13,
          14, 15,
          15, 16,
          16, 17,
          17, 18,
          18, 19,
          19, 20,

          0, 7,
          7, 14,
          1, 8,
          8, 15,
          2, 9,
          9, 16,
          3, 10,
          10, 17,
          4, 11,
          11, 18,
          5, 12,
          12, 19,
          6, 13,
          13, 20
        };

        // vertices-at-quad array
        static const Index v_q[] =
        {
          0, 1, 7, 8,
          1, 2, 8, 9,
          2, 3, 9, 10,
          3, 4, 10, 11,
          4, 5, 11, 12,
          5, 6, 12, 13,
          7, 8, 14, 15,
          8, 9, 15, 16,
          9, 10, 16, 17,
          10, 11, 17, 18,
          11, 12, 18, 19,
          12, 13, 19, 20
        };

        // edges-at-quad array
        static const Index e_q[] =
        {
          0, 6, 18, 20,
          1, 7, 20, 22,
          2, 8, 22, 24,
          3, 9, 24, 26,
          4, 10, 26, 28,
          5, 11, 28, 30,

          6, 12, 19, 21,
          7, 13, 21, 23,
          8, 14, 23, 25,
          9, 15, 25, 27,
          10, 16, 27, 29,
          11, 17, 29, 31
        };

        // get struct- index sets
        StructIndexSet<2,1,0> set_v_e = mesh->get_index_set<1,0>();
        StructIndexSet<2,2,0> set_v_q = mesh->get_index_set<2,0>();
        StructIndexSet<2,2,1> set_e_q = mesh->get_index_set<2,1>();

        // check vertex at edge
        Index i(0);
        for(Index j(0); j < 32; ++j)
        {
          for(int k(0); k < 2; ++k)
          {
            if(set_v_e(j,k) != v_e[i])
            {
              throw String("Vertex-At-Edge index set error");
            }
            ++i;
          }
        }

        // check vertex at quad
        i = 0;
        for(Index j(0); j < 12; ++j)
        {
          for(int k(0); k < 4; ++k)
          {
            if(set_v_q(j,k) != v_q[i])
            {
              throw String("Vertex-At-Quad index set error");
            }
            ++i;
          }
        }

        //check edge at quad
        i = 0;
        for(Index j(0); j < 12; ++j)
        {
          for(int k(0); k < 4; ++k)
          {
            if(set_e_q(j,k) != e_q[i])
            {
              throw String("Edge-At-Quad index set error");
            }
            ++i;
          }
        }
      } // validate_structured_mesh_2d

      void validate_structured_mesh_3d(const StructuredMesh<3>* mesh)
      {

        // validate sizes
        if(mesh->get_num_entities(0) != 60)
          throw String("Vertex count mismatch");
        if(mesh->get_num_entities(1) != 133)
          throw String("Edge count mismatch");
        if(mesh->get_num_entities(2) != 98)
          throw String("Quad count mismatch");
        if(mesh->get_num_entities(3) != 24)
          throw String("Hexa count mismatch");

        // vertices-at-edge array
        static const Index v_e[] =
        {
          // x direction
          0, 1,
          1, 2,
          2, 3,
          3, 4,

          5, 6,
          6, 7,
          7, 8,
          8, 9,

          10, 11,
          11, 12,
          12, 13,
          13, 14,

          15, 16,
          16, 17,
          17, 18,
          18, 19,

          20, 21,
          21, 22,
          22, 23,
          23, 24,

          25, 26,
          26, 27,
          27, 28,
          28, 29,

          30, 31,
          31, 32,
          32, 33,
          33, 34,

          35, 36,
          36, 37,
          37, 38,
          38, 39,

          40, 41,
          41, 42,
          42, 43,
          43, 44,

          45, 46,
          46, 47,
          47, 48,
          48, 49,

          50, 51,
          51, 52,
          52, 53,
          53, 54,

          55, 56,
          56, 57,
          57, 58,
          58, 59,

          // y direction
          0, 5,
          5, 10,
          1, 6,
          6, 11,
          2, 7,
          7, 12,
          3, 8,
          8, 13,
          4, 9,
          9, 14,
          15, 20,
          20, 25,
          16, 21,
          21, 26,
          17, 22,
          22, 27,
          18, 23,
          23, 28,
          19, 24,
          24, 29,
          30, 35,
          35, 40,
          31, 36,
          36, 41,
          32, 37,
          37, 42,
          33, 38,
          38, 43,
          34, 39,
          39, 44,
          45, 50,
          50, 55,
          46, 51,
          51, 56,
          47, 52,
          52, 57,
          48, 53,
          53, 58,
          49, 54,
          54, 59,

          // z direction
          0, 15,
          15, 30,
          30, 45,
          1, 16,
          16, 31,
          31, 46,
          2, 17,
          17, 32,
          32, 47,
          3, 18,
          18, 33,
          33, 48,
          4, 19,
          19, 34,
          34, 49,

          5, 20,
          20, 35,
          35, 50,
          6, 21,
          21, 36,
          36, 51,
          7, 22,
          22, 37,
          37, 52,
          8, 23,
          23, 38,
          38, 53,
          9, 24,
          24, 39,
          39, 54,

          10, 25,
          25, 40,
          40, 55,
          11, 26,
          26, 41,
          41, 56,
          12, 27,
          27, 42,
          42, 57,
          13, 28,
          28, 43,
          43, 58,
          14, 29,
          29, 44,
          44, 59
        };

        // vertices-at-quad array
        static const Index v_q[] =
        {
          // z normal
          0, 1, 5, 6,
          1, 2, 6, 7,
          2, 3, 7, 8,
          3, 4, 8, 9,
          5, 6, 10, 11,
          6, 7, 11, 12,
          7, 8, 12, 13,
          8, 9, 13, 14,
          15, 16, 20, 21,
          16, 17, 21, 22,
          17, 18, 22, 23,
          18, 19, 23, 24,
          20, 21, 25, 26,
          21, 22, 26, 27,
          22, 23, 27, 28,
          23, 24, 28, 29,
          30, 31, 35, 36,
          31, 32, 36, 37,
          32, 33, 37, 38,
          33, 34, 38, 39,
          35, 36, 40, 41,
          36, 37, 41, 42,
          37, 38, 42, 43,
          38, 39, 43, 44,
          45, 46, 50, 51,
          46, 47, 51, 52,
          47, 48, 52, 53,
          48, 49, 53, 54,
          50, 51, 55, 56,
          51, 52, 56, 57,
          52, 53, 57, 58,
          53, 54, 58, 59,

          // y normal
          0, 1, 15, 16,
          1, 2, 16, 17,
          2, 3, 17, 18,
          3, 4, 18, 19,
          15, 16, 30, 31,
          16, 17, 31, 32,
          17, 18, 32, 33,
          18, 19, 33, 34,
          30, 31, 45, 46,
          31, 32, 46, 47,
          32, 33, 47, 48,
          33, 34, 48, 49,
          5, 6, 20, 21,
          6, 7, 21, 22,
          7, 8, 22, 23,
          8, 9, 23, 24,
          20, 21, 35, 36,
          21, 22, 36, 37,
          22, 23, 37, 38,
          23, 24, 38, 39,
          35, 36, 50, 51,
          36, 37, 51, 52,
          37, 38, 52, 53,
          38, 39, 53, 54,
          10, 11, 25, 26,
          11, 12, 26, 27,
          12, 13, 27, 28,
          13, 14, 28, 29,
          25, 26, 40, 41,
          26, 27, 41, 42,
          27, 28, 42, 43,
          28, 29, 43, 44,
          40, 41, 55, 56,
          41, 42, 56, 57,
          42, 43, 57, 58,
          43, 44, 58, 59,

          // x normal
          0, 5, 15, 20,
          5, 10, 20, 25,
          15, 20, 30, 35,
          20, 25, 35, 40,
          30, 35, 45, 50,
          35, 40, 50, 55,

          1, 6, 16, 21,
          6, 11, 21, 26,
          16, 21, 31, 36,
          21, 26, 36, 41,
          31, 36, 46, 51,
          36, 41, 51, 56,

          2, 7, 17, 22,
          7, 12, 22, 27,
          17, 22, 32, 37,
          22, 27, 37, 42,
          32, 37, 47, 52,
          37, 42, 52, 57,

          3, 8, 18, 23,
          8, 13, 23, 28,
          18, 23, 33, 38,
          23, 28, 38, 43,
          33, 38, 48, 53,
          38, 43, 53, 58,

          4, 9, 19, 24,
          9, 14, 24, 29,
          19, 24, 34, 39,
          24, 29, 39, 44,
          34, 39, 49, 54,
          39, 44, 54, 59
        };

        // vertices-at-hexa array
        static const Index v_h[] =
        {
          0, 1, 5, 6, 15, 16, 20, 21,
          1, 2, 6, 7, 16, 17, 21, 22,
          2, 3, 7, 8, 17, 18, 22, 23,
          3, 4, 8, 9, 18, 19, 23, 24,
          5, 6, 10, 11, 20, 21, 25, 26,
          6, 7, 11, 12, 21, 22, 26, 27,
          7, 8, 12, 13, 22, 23, 27, 28,
          8, 9, 13, 14, 23, 24, 28, 29,

          15, 16, 20, 21, 30, 31, 35, 36,
          16, 17, 21, 22, 31, 32, 36, 37,
          17, 18, 22, 23, 32, 33, 37, 38,
          18, 19, 23, 24, 33, 34, 38, 39,
          20, 21, 25, 26, 35, 36, 40, 41,
          21, 22, 26, 27, 36, 37, 41, 42,
          22, 23, 27, 28, 37, 38, 42, 43,
          23, 24, 28, 29, 38, 39, 43, 44,

          30, 31, 35, 36, 45, 46, 50, 51,
          31, 32, 36, 37, 46, 47, 51, 52,
          32, 33, 37, 38, 47, 48, 52, 53,
          33, 34, 38, 39, 48, 49, 53, 54,
          35, 36, 40, 41, 50, 51, 55, 56,
          36, 37, 41, 42, 51, 52, 56, 57,
          37, 38, 42, 43, 52, 53, 57, 58,
          38, 39, 43, 44, 53, 54, 58, 59
        };

        // edges-at-quad array
        static const Index e_q[] =
        {
          // z normal
          0, 4, 48, 50,
          1, 5, 50, 52,
          2, 6, 52, 54,
          3, 7, 54, 56,
          4, 8, 49, 51,
          5, 9, 51, 53,
          6, 10, 53, 55,
          7, 11, 55, 57,
          12, 16, 58, 60,
          13, 17, 60, 62,
          14, 18, 62, 64,
          15, 19, 64, 66,
          16, 20, 59, 61,
          17, 21, 61, 63,
          18, 22, 63, 65,
          19, 23, 65, 67,
          24, 28, 68, 70,
          25, 29, 70, 72,
          26, 30, 72, 74,
          27, 31, 74, 76,
          28, 32, 69, 71,
          29, 33, 71, 73,
          30, 34, 73, 75,
          31, 35, 75, 77,
          36, 40, 78, 80,
          37, 41, 80, 82,
          38, 42, 82, 84,
          39, 43, 84, 86,
          40, 44, 79, 81,
          41, 45, 81, 83,
          42, 46, 83, 85,
          43, 47, 85, 87,

          // y normal
          0, 12, 88, 91,
          1, 13, 91, 94,
          2, 14, 94, 97,
          3, 15, 97, 100,
          12, 24, 89, 92,
          13, 25, 92, 95,
          14, 26, 95, 98,
          15, 27, 98, 101,
          24, 36, 90, 93,
          25, 37, 93, 96,
          26, 38, 96, 99,
          27, 39, 99, 102,
          4, 16, 103, 106,
          5, 17, 106, 109,
          6, 18, 109, 112,
          7, 19, 112, 115,
          16, 28, 104, 107,
          17, 29, 107, 110,
          18, 30, 110, 113,
          19, 31, 113, 116,
          28, 40, 105, 108,
          29, 41, 108, 111,
          30, 42, 111, 114,
          31, 43, 114, 117,
          8, 20, 118, 121,
          9, 21, 121, 124,
          10, 22, 124, 127,
          11, 23, 127, 130,
          20, 32, 119, 122,
          21, 33, 122, 125,
          22, 34, 125, 128,
          23, 35, 128, 131,
          32, 44, 120, 123,
          33, 45, 123, 126,
          34, 46, 126, 129,
          35, 47, 129, 132,

          // x normal
          48, 58, 88, 103,
          49, 59, 103, 118,
          58, 68, 89, 104,
          59, 69, 104, 119,
          68, 78, 90, 105,
          69, 79, 105, 120,
          50, 60, 91, 106,
          51, 61, 106, 121,
          60, 70, 92, 107,
          61, 71, 107, 122,
          70, 80, 93, 108,
          71, 81, 108, 123,
          52, 62, 94, 109,
          53, 63, 109, 124,
          62, 72, 95, 110,
          63, 73, 110, 125,
          72, 82, 96, 111,
          73, 83, 111, 126,
          54, 64, 97, 112,
          55, 65, 112, 127,
          64, 74, 98, 113,
          65, 75, 113, 128,
          74, 84, 99, 114,
          75, 85, 114, 129,
          56, 66, 100, 115,
          57, 67, 115, 130,
          66, 76, 101, 116,
          67, 77, 116, 131,
          76, 86, 102, 117,
          77, 87, 117, 132
        };

        // edges-at-hexa array
        static const Index e_h[] =
        {
          0, 4, 12, 16, 48, 50, 58, 60, 88, 91, 103, 106,
          1, 5, 13, 17, 50, 52, 60, 62, 91, 94, 106, 109,
          2, 6, 14, 18, 52, 54, 62, 64, 94, 97, 109, 112,
          3, 7, 15, 19, 54, 56, 64, 66, 97, 100, 112, 115,
          4, 8, 16, 20, 49, 51, 59, 61, 103, 106, 118, 121,
          5, 9, 17, 21, 51, 53, 61, 63, 106, 109, 121, 124,
          6, 10, 18, 22, 53, 55, 63, 65, 109, 112, 124, 127,
          7, 11, 19, 23, 55, 57, 65, 67, 112, 115, 127, 130,
          12, 16, 24, 28, 58, 60, 68, 70, 89, 92, 104, 107,
          13, 17, 25, 29, 60, 62, 70, 72, 92, 95, 107, 110,
          14, 18, 26, 30, 62, 64, 72, 74, 95, 98, 110, 113,
          15, 19, 27, 31, 64, 66, 74, 76, 98, 101, 113, 116,
          16, 20, 28, 32, 59, 61, 69, 71, 104, 107, 119, 122,
          17, 21, 29, 33, 61, 63, 71, 73, 107, 110, 122, 125,
          18, 22, 30, 34, 63, 65, 73, 75, 110, 113, 125, 128,
          19, 23, 31, 35, 65, 67, 75, 77, 113, 116, 128, 131,
          24, 28, 36, 40, 68, 70, 78, 80, 90, 93, 105, 108,
          25, 29, 37, 41, 70, 72, 80, 82, 93, 96, 108, 111,
          26, 30, 38, 42, 72, 74, 82, 84, 96, 99, 111, 114,
          27, 31, 39, 43, 74, 76, 84, 86, 99, 102, 114, 117,
          28, 32, 40, 44, 69, 71, 79, 81, 105, 108, 120, 123,
          29, 33, 41, 45, 71, 73, 81, 83, 108, 111, 123, 126,
          30, 34, 42, 46, 73, 75, 83, 85, 111, 114, 126, 129,
          31, 35, 43, 47, 75, 77, 85, 87, 114, 117, 129, 132
        };

        // quad-at-hexa array
        static const Index q_h[] =
        {
          0, 8, 32, 44, 68, 74,
          1, 9, 33, 45, 74, 80,
          2, 10, 34, 46, 80, 86,
          3, 11, 35, 47, 86, 92,
          4, 12, 44, 56, 69, 75,
          5, 13, 45, 57, 75, 81,
          6, 14, 46, 58, 81, 87,
          7, 15, 47, 59, 87, 93,
          8, 16, 36, 48, 70, 76,
          9, 17, 37, 49, 76, 82,
          10, 18, 38, 50, 82, 88,
          11, 19, 39, 51, 88, 94,
          12, 20, 48, 60, 71, 77,
          13, 21, 49, 61, 77, 83,
          14, 22, 50, 62, 83, 89,
          15, 23, 51, 63, 89, 95,
          16, 24, 40, 52, 72, 78,
          17, 25, 41, 53, 78, 84,
          18, 26, 42, 54, 84, 90,
          19, 27, 43, 55, 90, 96,
          20, 28, 52, 64, 73, 79,
          21, 29, 53, 65, 79, 85,
          22, 30, 54, 66, 85, 91,
          23, 31, 55, 67, 91, 97
        };

        // get struct- index sets
        StructIndexSet<3,1,0> set_v_e = mesh->get_index_set<1,0>();
        StructIndexSet<3,2,0> set_v_q = mesh->get_index_set<2,0>();
        StructIndexSet<3,3,0> set_v_h = mesh->get_index_set<3,0>();
        StructIndexSet<3,2,1> set_e_q = mesh->get_index_set<2,1>();
        StructIndexSet<3,3,1> set_e_h = mesh->get_index_set<3,1>();
        StructIndexSet<3,3,2> set_q_h = mesh->get_index_set<3,2>();

        // check vertex at edge
        Index i(0);
        for(Index j(0); j < 133; ++j)
        {
          for(int k(0); k < 2; ++k)
          {
            if(set_v_e(j,k) != v_e[i])
            {
              throw String("Vertex-At-Edge index set error");
            }
            ++i;
          }
        }

        // check vertex at quad
        i = 0;
        for(Index j(0); j < 98; ++j)
        {
          for(int k(0); k < 4; ++k)
          {
            if(set_v_q(j,k) != v_q[i])
            {
              throw String("Vertex-At-Quad index set error");
            }
            ++i;
          }
        }

        // check vertex at hexa
        i = 0;
        for(Index j(0); j < 24; ++j)
        {
          for(int k(0); k < 8; ++k)
          {
            if(set_v_h(j,k) != v_h[i])
            {
              throw String("Vertex-At-Hexa index set error");
            }
            ++i;
          }
        }

        // check edge at quad
        i = 0;
        for(Index j(0); j < 98; ++j)
        {
          for(int k(0); k < 4; ++k)
          {
            if(set_e_q(j,k) != e_q[i])
            {
              throw String("Edge-At-Quad index set error");
            }
            ++i;
          }
        }

        // check edge at hexa
        i = 0;
        for(Index j(0); j < 24; ++j)
        {
          for(int k(0); k < 12; ++k)
          {
            if(set_e_h(j,k) != e_h[i])
            {
              throw String("Edge-At-Hexa index set error");
            }
            ++i;
          }
        }

        // check quad at hexa
        i = 0;
        for(Index j(0); j < 24; ++j)
        {
          for(int k(0); k < 6; ++k)
          {
            if(set_q_h(j,k) != q_h[i])
            {
              throw String("Quad-At-Hexa index set error");
            }
            ++i;
          }
        }

      } // validate_structured_mesh_3d

    } // namespace TestAux
  } // namespace Geometry
} // namespace FEAT
